generator是指一個函式,能夠產生一個sequence,但每產生一個值後,就會傳回值並將函式保持在此狀態,直到下一次呼叫此函式
In [1]:
# 這是一個 infinite generator,用來產生Fibonacci數列
def fibonacci():
i, j = 0, 1
while True:
yield j # 當傳回 j 之後,函式會停留在這一行,直到下一次呼叫為止
i, j = j, i + j
In [2]:
# 印出1~500的fibonacci sequence
for x in fibonacci():
if x > 500: break
print x,
itertools
這個library提供許多generator相關的函式。
imap(func, p, q)
: 傳回func(p[i], q[i])
ifilter(pred_func, seq)
: 傳回seq
中使pred_func(x)==True
的值。pred_func==None
,則傳回seq[i]==True
的值ifilterfalse(pred_func, seq)
: 傳回seq
中使pred_func(x)==False
的值。pred_func==None
,則傳回seq[i]==False
的值izip(p, q)
: 傳回tuple (p[i], q[i])
,如果p,q
長度不相等,會以短的為主izip_longest(p, q)
: 傳回tuple (p[i], q[i])
,如果p,q
長度不相等,會以長的為主compress(data, sel)
: 傳回data[i] if sel[i]
chain(p1, p2, ...)
: 傳回p1[0],...,p1[-1],p2[0],...,p2[-1],...
takewhile(pred, seq)
: 傳回seq[i]
直到pred(seq[i])==False
dropwhile(pred, seq)
: 傳回sen[i]
,從使得pred(seq[i])==False
的i
開始islice(seq [,start] ,stop [,step])
: 傳回seq[range(start, stop, step)]
groupby(seq [,key])
: 用來產生iterator of iterators。next(groupby(seq, key))
,會傳回(key, iterator)
的組合。iterator
會依序傳回seq[i]
,直到key(seq[i])
改變為止。key(seq)==[1,1,0,0,1]
,則會產生三個(1, it1), (0, it2), (1, it3)
,其中it1
產生seq[0],seq[1]
,it3
產生seq[4]
。key
,則key==seq[i]
。itertools
也有提供現成的generator:
count(start [,step])
: 從start, start+step, ...
開始的infinite generatorcycle(seq)
: 循環產生seq[0],...,seq[-1],seq[0],...
的infinite generatorrepeat(elem [,n])
: 產生n
個elem
,如果n
沒有指定會變成infinite generator
In [3]:
from itertools import *
In [4]:
a = [1, 5, 8, 3, 6, 9, 2, 4, 7]
b = [11, 12, 13, 14]
In [5]:
list(imap(pow, b, a)) # 傳回 11^1, 12^5, 13^8, 14^3
Out[5]:
In [6]:
list(ifilter(lambda x: x % 2, a)) # 傳回所有奇數
Out[6]:
In [7]:
list(ifilterfalse(lambda x: x % 2, a)) # 傳回所有偶數
Out[7]:
In [8]:
list(izip(a, b)) # 結合成tuple,以短的為主
Out[8]:
In [9]:
list(izip_longest(a, b)) # 結合成tuple,以長的為主,空的地方填 None
Out[9]:
In [10]:
list(izip_longest(a, b, fillvalue=20)) # 結合成tuple,以長的為主,空的地方填 20
Out[10]:
In [11]:
list(compress('HELLO', [0, 1, 1, 0, 1])) # 根據 boolean selector 選擇元素
Out[11]:
In [12]:
list(takewhile(lambda x: x != 9, a)) # 當 pred_func 傳回 False 時停止
Out[12]:
In [13]:
list(dropwhile(lambda x: x != 9, a)) # 當 pred_func 傳回 False 時開始
Out[13]:
In [14]:
list(islice(fibonacci(), 3, 10, 2)) # 取出第 3, 5, 7, 9 個Fibonacci數
Out[14]:
In [15]:
for k, it in groupby([1, 1, 2, 2, 2, 3, 1, 1]): # 如果groupby沒有指定key,則iterable裡每個值都是自己的key
print list(it)
In [16]:
for k, it in groupby(a, lambda x: x == 9): # 當key值改變時,會產生新的iterator
print list(it)
排列組合相關的function:
product(p, q)
: 傳回所有(p[i],q[j])
的組合,總數應該是len(p)*len(q)
permutations(p, [,r])
: 傳回p
中取r
個元素所有可能的排列,如果不指定r
則會用所有元素combinations(p, r)
: 傳回p
中取r
個元素的所有組合combinations_with_replacement(p, r)
: 傳回p
中取r
個元素的所有組合,但元素可重複出現
In [17]:
list(product([1,2], [3,4,5]))
Out[17]:
In [18]:
list(permutations([1, 2, 3]))
Out[18]:
In [19]:
list(permutations([1, 2, 3], 2))
Out[19]:
In [20]:
list(combinations([1, 2, 3], 2))
Out[20]:
In [21]:
list(combinations_with_replacement([1, 2, 3], 2))
Out[21]:
next(iterator [,default])
的用途是取得iterator的下一個元素
default
有設任何值(例如None
),當iterator清空時,會傳回default
default
沒有設,當iterator清空時,會產生StopIteration
In [22]:
it = (i for i in b)
print next(it), next(it), next(it), next(it), next(it)
要消耗一個iterator的前n個元素,可以結合next
及islice
。
islice(iterator, n, n)
會取出iterator前n個元素並丟棄
In [23]:
iterator = izip(a, b) # 內容是 (1, 11), (5, 12), (8, 13), (3, 14)
next(islice(iterator, 2, 2), None) # (1, 11), (5, 12) 被丟掉了
list(iterator)
Out[23]:
要消耗一個iterator的所有元素,可以用collections.deque
,它會一直取iterator的元素直到清空為止。
為了減少記憶體用量,collections.deque
的大小可設為0,則取出的元素就會直接丟棄。
In [24]:
from collections import deque
iterator = izip(a, b)
deque(iterator, maxlen=0)
list(iterator)
Out[24]:
計算符合條件的元素個數,可以結合sum
與imap
In [25]:
iterator = permutations([1, 2, 3])
sum(imap(lambda x: x[1] == 2, iterator)) # 符合條件的是 (1, 2, 3), (3, 2, 1)
Out[25]:
用有限長度的list
產生無限長度的generator,但後面都填None
In [26]:
chain(permutations([1, 2, 3]), repeat(None))
Out[26]:
將list
of list
結合成一個list
In [27]:
# 注意: list層數只會少一層,例如下面的 [8, 9] 仍然存在
list(chain.from_iterable([[1, 3], [4, 5], [6, [8, 9]]]))
Out[27]:
將list
變成每n個一組的tuple
In [28]:
args = [iter('ABCDEFG')] * 3 # args是一個list of iterators [it, it, it],但三個it都代表同一個iterator
list(izip_longest(*args)) # 用 *args 將list展開成三個參數
Out[28]:
列出所有組合 (powerset)
In [29]:
list(chain.from_iterable(combinations([1, 2, 3], r) for r in range(4)))
Out[29]:
In [ ]: